package felix.fuse.mount.service;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;

/**
 * 管理服务组件的生命周期
 */
public class ContextContainer {

    private static final Logger log = LoggerFactory.getLogger(ContextContainer.class);

    private static final ConcurrentMap<String, Object> context = new ConcurrentHashMap<>(24);

    public static void init() {
        ContextContainer.create(LogEventService.class);
        ContextContainer.create(UploadFileToRemote.class)
                .setS3Service(ContextContainer.create(S3Service.class));
        ContextContainer.create(S3Fuse.class);
    }

    public static <T> T create(Class<T> cls, String name) {
        try {
            T obj = cls.getDeclaredConstructor().newInstance();
            if (context.get(name) != null) {
                destroy(obj);
            }
            register(name, obj);
            return obj;
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            return null;
        }
    }

    public static <T> T create(Class<T> cls) {
        return create(cls, cls.getName());
    }

    public static void destroy(Object obj) {
        if (obj instanceof BaseService) {
            ((BaseService) obj).destroy();
        }
    }

    public static void destroy() {
        for (Object obj : context.values()) {
            if (obj instanceof BaseService) {
                ((BaseService) obj).destroy();
            }
        }
    }

    public static <T> void register(String name, T obj) {
        init(obj);
        context.put(name, obj);
    }

    public static <T> void register(T obj) {
        register(obj.getClass().getName(), obj);
    }

    private static void init(Object obj) {
        if (obj instanceof BaseService) {
            ((BaseService) obj).init();
        }
    }

    public static <T> T get(Class<T> cls, String name) {
        return (T) context.get(name);
    }

    public static <T> T get(Class<T> cls) {
        return get(cls, cls.getName());
    }
}
